package utils;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by liming on 2016/5/16.
 * google 二维码生成
 */
public class QrCodesUtils {

    /**
     * 检查是否ImageIO支持的文件格式
     * @param sFormat
     * @return
     */
    private boolean checkIsImageIOFormat(String sFormat){
        boolean bReturn = false;
        String[] readerSuff= ImageIO.getReaderFormatNames();//搜索;
        for(int i=0;i<readerSuff.length;i++){
            if (readerSuff[i].toLowerCase().equals(sFormat.toLowerCase())){
                bReturn = true;
                break;
            }
        }
        return bReturn;
    }

    /**
     * 生成带图片的二维码
     * @param ImgLogo   二维码中间的图片
     * @param iImageLength 图片的宽度  宽高一致
     * @param iFrameWidth 边框宽度
     * @param sContent 内容
     * @param sCharacter 编码
     * @param iWidth 二维码宽度
     * @param iHeight 二维码高度
     * @param iFrameColor 边框颜色
     * @param iContentColor 内容颜色
     * @return
     */
    public BufferedImage encodeQRCodeToImage(BufferedImage ImgLogo, int iImageLength, int iFrameWidth, String sContent,
                                             String sCharacter, int iWidth, int iHeight,
                                             int iFrameColor, int iContentColor){
        BufferedImage imgReturn = new BufferedImage(iWidth, iHeight,
                BufferedImage.TYPE_INT_RGB);
        //像素点颜色
        int[][] rgbPixels = new int[iImageLength][iImageLength];
        for (int i = 0; i < ImgLogo.getWidth(); i++) {
            for (int j = 0; j < ImgLogo.getHeight(); j++) {
                rgbPixels[i][j] = ImgLogo.getRGB(i, j);
            }
        }

        Map<EncodeHintType, Object> ehtHints = new HashMap<EncodeHintType, Object>();
        ehtHints.put(EncodeHintType.CHARACTER_SET, sCharacter);
        ehtHints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);

        BitMatrix bitMatrix = null;// 生成矩阵
        try {
            bitMatrix = new MultiFormatWriter().encode(sContent,
                    BarcodeFormat.QR_CODE, iWidth, iHeight, ehtHints);

            int iHalfWidth = bitMatrix.getWidth() / 2;
            int iHalfHeight = bitMatrix.getHeight() / 2;
            int[] iMatrixPixels = new int[iWidth * iHeight];

            int iHalfImageLength = iImageLength / 2;


            for (int iY = 0; iY < bitMatrix.getHeight(); iY++) {
                for (int iX = 0; iX < bitMatrix.getWidth(); iX++) {
                    // 读取图片
                    if (iX > iHalfWidth - iHalfImageLength
                            && iX < iHalfWidth + iHalfImageLength
                            && iY > iHalfHeight - iHalfImageLength
                            && iY < iHalfHeight + iHalfImageLength) {
                        iMatrixPixels[iY * iWidth + iX] = rgbPixels[iX - iHalfWidth
                                + iHalfImageLength][iY - iHalfHeight + iHalfImageLength];
                    }
                    // 在图片四周形成边框
                    else if ((iX > iHalfWidth - iHalfImageLength - iFrameWidth
                            && iX < iHalfWidth - iHalfImageLength + iFrameWidth
                            && iY > iHalfHeight - iHalfImageLength - iFrameWidth && iY < iHalfHeight
                            + iHalfImageLength + iFrameWidth)
                            || (iX > iHalfWidth + iHalfImageLength - iFrameWidth
                            && iX < iHalfWidth + iHalfImageLength + iFrameWidth
                            && iY > iHalfHeight - iHalfImageLength - iFrameWidth && iY < iHalfHeight
                            + iHalfImageLength + iFrameWidth)
                            || (iX > iHalfWidth - iHalfImageLength - iFrameWidth
                            && iX < iHalfWidth + iHalfImageLength + iFrameWidth
                            && iY > iHalfHeight - iHalfImageLength - iFrameWidth && iY < iHalfHeight
                            - iHalfImageLength + iFrameWidth)
                            || (iX > iHalfWidth - iHalfImageLength - iFrameWidth
                            && iX < iHalfWidth + iHalfImageLength + iFrameWidth
                            && iY > iHalfHeight + iHalfImageLength - iFrameWidth && iY < iHalfHeight
                            + iHalfImageLength + iFrameWidth)) {
                        iMatrixPixels[iY * iWidth + iX] = iFrameColor;
                    } else {
                        // 此处可以修改二维码的颜色，可以分别制定二维码和背景的颜色；
                        iMatrixPixels[iY * iWidth + iX] = bitMatrix.get(iX, iY) ? iContentColor
                                : iFrameColor;
                    }
                }
            }

            imgReturn.getRaster().setDataElements(0, 0, iWidth, iHeight, iMatrixPixels);

        } catch (WriterException e) {
            e.printStackTrace();
            imgReturn = null;
        }

        return imgReturn;
    }

    /**
     * 保存二维码图片(google)
     * @param sContent 内容
     * @param sFileName 文件名称
     * @param sCharacter 编码格式
     * @param iWidth 宽度
     * @param iHeight 高度
     * @return
     */
    public boolean encodeQRCodeToFile(String sContent, String sFileName, String sCharacter,
                                      int iWidth, int iHeight) {
        boolean bReturn = true;
        if (sFileName.isEmpty() || sFileName.equals("")) return  false; //判断未输入文件名称
        String sPrefix = sFileName.substring(sFileName.lastIndexOf(".") + 1); //获取扩展名
        Map<EncodeHintType, Object> ehtHints = new HashMap<EncodeHintType, Object>();
        ehtHints.put(EncodeHintType.CHARACTER_SET, sCharacter);
        BitMatrix bitMatrix = null;// 生成矩阵
        try {
            bitMatrix = new MultiFormatWriter().encode(sContent,
                    BarcodeFormat.QR_CODE, iWidth, iHeight, ehtHints);

            Path path = FileSystems.getDefault().getPath(sFileName);
            //        sPrefix 异常还没有处理
            if (!checkIsImageIOFormat(sPrefix)) return false;  //检查支持格式
            try {
                MatrixToImageWriter.writeToPath(bitMatrix, sPrefix, path);// 输出图像
            } catch (IOException e) {
                bReturn = false;
                e.printStackTrace();
            }

        } catch (WriterException e) {
            bReturn = false;
            e.printStackTrace();
        }
        return bReturn;
    }

    /**
     * 保存带图片的二维码
     * @param sFileName 保存的文件名称
     * @param ImgLogo 二维码中间的图片
     * @param iImageLength 图片的宽度  宽高一致
     * @param iFrameWidth 边框宽度
     * @param sContent 数据
     * @param sCharacter 编码
     * @param iWidth 宽度
     * @param iHeight 高度
     * @param iFrameColor 边框颜色
     * @param iContentColor 内容颜色
     * @return
     */
    public boolean encodeQRCodeToFile(String sContent, String sFileName, String sCharacter, int iWidth, int iHeight,
                                      BufferedImage ImgLogo, int iImageLength, int iFrameWidth, int iFrameColor,
                                      int iContentColor){
        boolean bReturn = true;
        if (sFileName.isEmpty() || sFileName.equals("")) return  false; //判断未输入文件名称
        String sPrefix = sFileName.substring(sFileName.lastIndexOf(".") + 1); //获取扩展名
        if (!checkIsImageIOFormat(sPrefix)) return false;  //检查支持格式
        BufferedImage imgReturn = encodeQRCodeToImage(ImgLogo, iImageLength, iFrameWidth, sContent, sCharacter, iWidth,
                iHeight, iFrameColor, iContentColor);
        bReturn = (imgReturn !=null);
        if (bReturn){
            try {
                ImageIO.write(imgReturn, sPrefix, new File(sFileName));
            } catch (IOException e) {
                e.printStackTrace();
                bReturn = false;
            }
        }
        return bReturn;
    }


    /**
     *保存二维码流(google)
     * @param sContent 内容
     * @param sCharacter 编码
     * @param sPrefix 扩展名
     * @param iWidth 宽度
     * @param iHeight 高度
     * @param outputStream 返回流
     * @return
     */
    public boolean encodeQRCodeToStream(String sContent, String sCharacter, String sPrefix, int iWidth, int iHeight,
                                        OutputStream outputStream) {
        boolean bReturn = true;
        Map<EncodeHintType, Object> ehtHints = new HashMap<EncodeHintType, Object>();
        ehtHints.put(EncodeHintType.CHARACTER_SET, sCharacter);
        BitMatrix bitMatrix = null;// 生成矩阵
        try {
            bitMatrix = new MultiFormatWriter().encode(sContent,
                    BarcodeFormat.QR_CODE, iWidth, iHeight, ehtHints);

            if (!checkIsImageIOFormat(sPrefix)) return false;  //检查支持格式
            try {
                //        sPrefix 异常还没有处理 主要为扩展名问题
                MatrixToImageWriter.writeToStream(bitMatrix, sPrefix, outputStream);
            } catch (IOException e) {
                bReturn = false;
                e.printStackTrace();
            }

        } catch (WriterException e) {
            bReturn = false;
            e.printStackTrace();
        }
        return bReturn;
    }


    /**
     * 保存二维码流(带图片)
     * @param outputStream 返回流
     * @param sPrefix 扩展名
     * @param ImgLogo 二维码中间的图片
     * @param iImageLength 图片的宽度  宽高一致
     * @param iFrameWidth 边框宽度
     * @param sContent 数据
     * @param sCharacter 编码
     * @param iWidth 宽度
     * @param iHeight 高度
     * @param iFrameColor 边框颜色
     * @param iContentColor 内容颜色
     * @return
     */
    public boolean encodeQRCodeToStream(String sContent, String sCharacter, String sPrefix, int iWidth, int iHeight,
                                        OutputStream outputStream, BufferedImage ImgLogo, int iImageLength,
                                        int iFrameWidth, int iFrameColor, int iContentColor){
        boolean bReturn = true;
        Map<EncodeHintType, Object> ehtHints = new HashMap<EncodeHintType, Object>();
        ehtHints.put(EncodeHintType.CHARACTER_SET, sCharacter);
        if (!checkIsImageIOFormat(sPrefix)) return false;  //检查支持格式
        BufferedImage imgReturn = encodeQRCodeToImage(ImgLogo, iImageLength, iFrameWidth, sContent, sCharacter, iWidth,
                iHeight, iFrameColor, iContentColor);
        bReturn = (imgReturn !=null);
        if (bReturn){
            try {
                ImageIO.write(imgReturn, sPrefix, outputStream);
            } catch (IOException e) {
                e.printStackTrace();
                bReturn = false;
            }
        }
        return bReturn;
    }

    /**
     *解析图片(google)
     * @param image   传入图片
     * @param sCharacter //编码方式
     * @return
     */
    public String decodeQRCodeFromImage(BufferedImage image, String sCharacter){
        String sReturn = "";
        try {
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, sCharacter);
            Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码
            sReturn = result.getText();
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        return  sReturn;
    }


}
